package ua.amsoft.brelok.chart;

import java.util.ArrayList;
import java.util.List;

import ua.amsoft.brelok.dto.Range;
import ua.amsoft.brelok.dto.Zone;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.Log;

/**
 * An {@link Drawable} extension for drawing the pie chart
 * 
 * @author Tair Mustafaiev
 */
public class BrelokPieChartDrawable extends Drawable {
    
    private final static String TAG = BrelokPieChartDrawable.class.getName();
    
    private final int paddingTop = 10;
    private final int paddingBottom = 10;
    
    private final int paddingLeft = 10;
    private final int paddingRight = 10;
    
    private int width;
    private int height;
    
    private final Paint paint;
    
    private final List<Integer> dataValues;
    private final List<Integer> colorValues;
    
    /**
     * Constructor
     * 
     * @param chart - chart objects with values to be drawed
     */
    public BrelokPieChartDrawable(final Range chart) {
        this.dataValues = new ArrayList<Integer>();
        this.colorValues = new ArrayList<Integer>();
        initChartZoneValues(chart);
        this.paint = new Paint();
    }
    
    /**
     * Initializes the values for drawing the pie chart
     * 
     * @param chart - chart objects with values to be drawed
     */
    private void initChartZoneValues(final Range chart) {
        final List<Zone> zones = chart.getZones();
        this.height = chart.getHeight();
        this.width = chart.getWidth();
        if (zones != null) {
            for (final Zone chartZone : zones) {
                this.dataValues.add(chartZone.getSize());
                this.colorValues.add(Color.parseColor(chartZone.getColor()));
            }
        }
    }
    
    @Override
    public void draw(final Canvas canvas) {
        Log.i(BrelokPieChartDrawable.TAG, "Pie chart darwing start");
        
        final RectF arcBounds = calculateArcBounds();
        drawChart(canvas, arcBounds);
        Log.i(BrelokPieChartDrawable.TAG, "Pie chart darwing finished");
    }
    
    /**
     * Calculates arc's bounds
     * 
     * @return {@link RectF}
     */
    private RectF calculateArcBounds() {
        final int paddedHorizontalRoom = this.width - (this.paddingLeft + this.paddingRight);
        final int paddedVerticalRoom = this.height - (this.paddingTop + this.paddingBottom);
        
        final int size = Math.min(paddedHorizontalRoom, paddedVerticalRoom);
        
        final boolean stretch = false;
        final int leftEdge = this.paddingLeft + ((paddedHorizontalRoom - size) / 2);
        final int rightEdge = leftEdge + (stretch ? paddedHorizontalRoom : size);
        final int topEdge = this.paddingTop + ((paddedVerticalRoom - size) / 2);
        final int bottomEdge = topEdge + (stretch ? paddedVerticalRoom : size);
        
        final RectF arcBounds = new RectF(leftEdge, topEdge, rightEdge, bottomEdge);
        return arcBounds;
    }
    
    /**
     * Drawing the chart
     * 
     * @param canvas
     * @param arcBounds
     */
    private void drawChart(final Canvas canvas, final RectF arcBounds) {
        
        int valueSum = 0;
        for (final int dataValue : this.dataValues) {
            valueSum += dataValue;
        }
        
        float currentArcPositionDegrees = 0;
        int i = 0;
        for (final int dataValue : this.dataValues) {
            if (dataValue == 0) {
                continue;
            }
            Log.i(BrelokPieChartDrawable.TAG, "Pie chart zone drawing with value: " + dataValue);
            
            final float arcSweep = valueSum == 0 ? 0 : (360 * dataValue) / (float) valueSum;
            
            final float newArcPositionDegrees = currentArcPositionDegrees + arcSweep;
            
            final int flickrPink = this.colorValues.get(i % this.colorValues.size());
            this.paint.setColor(flickrPink);
            this.paint.setAntiAlias(true);
            this.paint.setStyle(Paint.Style.FILL);
            canvas.drawArc(arcBounds, currentArcPositionDegrees, arcSweep, true, this.paint);
            paintStroke();
            canvas.drawArc(arcBounds, currentArcPositionDegrees, arcSweep, true, this.paint);
            
            currentArcPositionDegrees = newArcPositionDegrees;
            i++;
        }
    }
    
    /**
     * Paints chart's stroke
     */
    private void paintStroke() {
        this.paint.setStyle(Paint.Style.STROKE);
        this.paint.setStrokeJoin(Join.ROUND);
        this.paint.setStrokeCap(Cap.ROUND);
        this.paint.setStrokeWidth(1);
        this.paint.setColor(Color.WHITE);
    }
    
    @Override
    public int getOpacity() {
        return this.paint.getAlpha();
    }
    
    @Override
    public void setAlpha(final int alpha) {
        this.paint.setAlpha(alpha);
    }
    
    @Override
    public void setColorFilter(final ColorFilter cf) {
        this.paint.setColorFilter(cf);
    }
    
}
